<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>宏任务和微任务</title>
</head>
<body>
  
</body>
<script>
// 什么是宏任务和微任务
// 宏任务包括：setTimeout setInterval Ajax DOM事件
// 微任务：Promise async/await
// 微任务比宏任务的执行时间要早
// 同步任务和异步任务
// JavaScript是单线程执行的语言，在同一个时间只能做一件事情。这就导致后面的任务需要等到前面的任务完成才能执行，如果前面的任务很耗时就会造成后面的任务一直等待。为了解决这个问题JS中出现了同步任务和异步任务。

// 同步任务:
// 在主线程上排队执行的任务只有前一个任务执行完毕，才能执行后一个任务，形成一个执行栈。
// 异步任务:
// 不进入主线程，而是进入任务队列，当主线程中的任务执行完毕，就从任务队列中取出任务放进主线程中来进行执行。由于主线程不断重复的获得任务、执行任务、再获取再执行，所以者种机制被叫做事件循环（Event Loop）
// 我们都知道 Js 是单线程的，但是一些高耗时操作带来了进程阻塞的问题。为了解决这个问题，Js 有两种任务的执行模式：同步模式（Synchronous）和异步模式（Asynchronous）
// 在异步模式下，创建异步任务主要分为宏任务与微任务两种。ES6 规范中，宏任务（Macrotask） 称为 Task， 微任务（Microtask） 称为 Jobs。宏任务是由宿主（浏览器、Node）发起的，而微任务由 JS 自身发起。
// 宏任务与微任务的几种创建方式

// 宏任务（Macrotask） 微任务（Microtask）
// setTimeout requestAnimationFrame（有争议）
// setInterval MutationObserver（浏览器环境）
// MessageChannel Promise.[ then/catch/finally ]
// I/O，事件队列 process.nextTick（Node环境）
// setImmediate（Node环境） queueMicrotask
// script（整体代码块）

// 1.主线程上宏任务、微任务执行顺序
console.log('---start---');//第一轮主线程
 
setTimeout(() => {
  console.log('setTimeout');  // 将回调代码放入个宏任务队列，第二轮宏任务执行
}, 0);
 
new Promise((resolve, reject) => {
  console.log('---Promise第一轮微任务同步执行---');//第一轮微任务同步执行(Promise初始化时，就会执行)
  resolve()
}).then(()=>{
  console.log('Promise.then实例成功回调执行'); // 将回调代码放入微任务队列，第一轮宏任务执行完后立即执行（这个是异步的）
});
 
console.log('---end---');//第一轮主线程结束
// 执行顺序：主线程 >> 主线程上创建的微任务 >> 主线程上创建的宏任务
// ---start---
// ---Promise第一轮微任务同步执行---
// ---end---
// Promise.then实例成功回调执行
// setTimeout


// 2.宏任务中包含微任务
// 宏任务队列 1
setTimeout(() => {
  // 宏任务队列 2.1
  console.log('timer_1');
  setTimeout(() => {
    // 宏任务队列 3
    console.log('timer_3')
  }, 0)
  new Promise(resolve => {
    resolve()
    console.log('new promise')
  }).then(() => {
    // 微任务队列 1
    console.log('promise then')
  })
}, 0)
 
setTimeout(() => {
  // 宏任务队列 2.2
  console.log('timer_2')
}, 0)
console.log('========== Sync queue ==========')

// 执行顺序：主线程 >> 主线程上的宏任务队列1 >> 宏任务队列1中创建的微任务
// ========== Sync queue ==========
// timer_1
// new promise
// promise then
// timer_2
// timer_3



  async function async1() {
      console.log('async1 start');
      await async2();
      console.log('async1 end');
  }
  async function async2() {
      console.log('async2');
  }
  
  console.log('script start');  // 1、
  
  setTimeout(function() {
      console.log('setTimeout');
  }, 0)
  
  async1();
  
  new Promise(function(resolve) {
      console.log('promise1');
      resolve();
  }).then(function() {
      console.log('promise2');
  });
  console.log('script end');
  // 结果：
  // script start
  // async1 start
  // async2
  // promise1
  // script end
  // async1 end
  // promise2
  // setTimeout


</script>
</html>